#include "Socket.h"

Socket::Socket(const std::string& host, port_type port){
	
	he=gethostbyname(host.c_str());	/*Direccion a donde se conecta*/

	if(he==NULL) error=1; /*Erroe en el host name*/
		 	
	sockfd=socket(AF_INET, SOCK_STREAM, 0 );/*Crea socket*/
	
	if(sockfd==-1) 	error=1; /*Error en el descriptor*/ 

	their_addr.sin_family = AF_INET; /* host byte order */
	their_addr.sin_port = htons(port); /*Puerto*/
	their_addr.sin_addr = *((struct in_addr *)he->h_addr);
	bzero(&(their_addr.sin_zero), 8);/*Pone en cero*/
	
	/*Trata de conectarse*/
	if(connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) ==-1 )
				error=1;	/*Error al conectarse*/

}

Socket::Socket(port_type port,int backlog){	
		  sockfd = socket(AF_INET, SOCK_STREAM, 0);
     	if (sockfd < 0) 
        	error=1 ;/*Error file Descriptor*/
     bzero((char *) &their_addr, sizeof(their_addr));
     their_addr.sin_family = AF_INET;
     their_addr.sin_addr.s_addr = INADDR_ANY;
     their_addr.sin_port = htons(port);
     if (bind(sockfd, (struct sockaddr *) &their_addr, sizeof(their_addr)) < 0) 
              error=1; /*Error de Bind*/
     
	if( listen(sockfd,backlog) ==-1)/*queda escuchando*/
			error=1;
			
}
	
Socket::Socket(int fd){
	sockfd=fd;
	
}
Socket::~Socket(){

	close(sockfd);
}

int Socket::recv(std::string& buf, size_t len){

	int leidos=0;
	int aux=0;
	char buffer[255];
    
	while(leidos<len){
			aux=read(sockfd,buffer+leidos,len);
    			  			
			if(aux!=-1)
					leidos=leidos+aux;
			if(aux==-1) { 
					printf("Error lectura\n"); 
					return	 0;
			}
		}/*fin while*/		
		buffer[aux]='\0';	
		buf.assign(buffer);	/*Crea el nuevo string*/
		return 1;
}

int Socket:: send(const std::string& buf){
	int n=0;	
	    	n=write(sockfd,buf.c_str(),buf.size());
	
		 if (n < 0) {
            	 printf("ERROR sending from socket\n");
	 		return 1;
    	}
	return 0;
}

Socket* Socket::accept(){
	
	struct sockaddr_in  cli_addr;
	int  clilen,  newsockfd;	
    clilen = sizeof( struct sockaddr );
    newsockfd = ::accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t*)&clilen);
    
	if (newsockfd < 0) 
          return NULL;
	else 
			return new Socket(newsockfd);
				
}
 Socket::operator bool () const{
			
	 	if(error==1)	
			return false;
		else 
			return true;
}

void Socket:: sincroniza(std::string s){
			
			char longitud[4];
			char lon[2];
			int i=0;
			i=sprintf(longitud, "%d", s.size());
			
			/*Sincroniza lo que se va a enviar*/
			sprintf(lon, "%d", i);
			std::string numero(lon);		
			send(numero);
			numero.assign(longitud);
			send(numero);
}
int Socket::sincroniza(){
			std::string tam;
			int tamanio=0;
			/*calcula cuanto tiene que leer*/
			recv(tam,1); 
			tamanio=atoi(tam.c_str());
			recv(tam,tamanio); 
			tamanio=atoi(tam.c_str());
			return tamanio;
}
